import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
import org.apache.pdfbox.text.TextPositionComparator;
import org.apache.pdfbox.util.QuickSort;

import javax.swing.text.Position;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.text.Bidi;
import java.text.Normalizer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CustomTextStripper extends PDFTextStripper {
    private static final boolean useCustomQuickSort;

    //    private static final String[] LIST_ITEM_EXPRESSIONS = { "^([\\uff10-\\uff19\\d]{1,2}[\\uff0e.]{1})*([\\uff10-\\uff19\\d]{1,2}[\\uff0e.]*)", "\\.", "\\d+\\.", "\\[\\d+\\]",
//            "\\d+\\)", "[A-Z]\\.", "[a-z]\\.", "[A-Z]\\)", "[a-z]\\)", "[IVXL]+\\.",
//            "[ivxl]+\\.", };
    public CustomTextStripper() throws IOException {
    }

    private List<Pattern> listOfPatterns = null;
    private static final String[] LIST_ITEM_EXPRESSIONS=new String[]{"\\.", "\\d+\\.", "\\[\\d+\\]", "\\d+\\)", "[A-Z]\\.", "[a-z]\\.", "[A-Z]\\)", "[a-z]\\)", "[IVXL]+\\.", "[ivxl]+\\."};;

    //    public CustomTextStripper() throws IOException {
//        this.lineSeparator = this.LINE_SEPARATOR;
//        this.wordSeparator = " ";
//        this.paragraphStart = "";
//        this.paragraphEnd = "";
//        this.pageStart = "";
//        this.pageEnd = this.LINE_SEPARATOR;
//        this.articleStart = "";
//        this.articleEnd = "";
//        this.currentPageNo = 0;
//        this.startPage = 1;
//        this.endPage = 2147483647;
//        this.startBookmark = null;
//        this.startBookmarkPageNumber = -1;
//        this.endBookmarkPageNumber = -1;
//        this.endBookmark = null;
//        this.suppressDuplicateOverlappingText = true;
//        this.shouldSeparateByBeads = true;
//        this.sortByPosition = false;
//        this.addMoreFormatting = false;
//        this.indentThreshold = defaultIndentThreshold;
//        this.dropThreshold = defaultDropThreshold;
//        this.spacingTolerance = 0.5F;
//        this.averageCharTolerance = 0.3F;
//        this.beadRectangles = null;
//        this.charactersByArticle = new ArrayList();
//        this.characterListMapping = new HashMap();
//        this.listOfPatterns = null;
//    }
    @Override
    protected List<Pattern> getListItemPatterns() {
        if (listOfPatterns == null) {
            listOfPatterns = new ArrayList<Pattern>();
            for (String expression : LIST_ITEM_EXPRESSIONS) {
                Pattern p = Pattern.compile(expression);
                listOfPatterns.add(p);
            }
        }
        return listOfPatterns;
    }

     static final class LineItem {
        public static CustomTextStripper.LineItem WORD_SEPARATOR = new CustomTextStripper.LineItem();
        private final TextPosition textPosition;

        public static CustomTextStripper.LineItem getWordSeparator() {
            return WORD_SEPARATOR;
        }

        private LineItem() {
            this.textPosition = null;
        }

        LineItem(TextPosition textPosition) {
            this.textPosition = textPosition;
        }

        public TextPosition getTextPosition() {
            return this.textPosition;
        }

        public boolean isWordSeparator() {
            return this.textPosition == null;
        }
    }

    public static CustomTextStripper.LineItem getWordSeparatorCopy() {
        return LineItem.WORD_SEPARATOR;
    }


    public void CustomTextStripper() throws IOException {
    }

    @Override
    protected void writeLineSeparator() throws IOException {
    }

    @Override
    protected void writeString(String str, List<TextPosition> textPositions) throws IOException {
        output.write(str);

        // you may process the line here itself, as and when it is obtained
    }

    @Override
    protected void writeParagraphSeparator() throws IOException {
        super.writeLineSeparator();
    }

    @Override
    protected void writeParagraphEnd() throws IOException {
//        super.writeLineSeparator();
    }

    @Override
    protected void writePageEnd() throws IOException {
//        super.writeLineSeparator();
    }

    static final class PositionWrapper {
        private boolean isLineStart = false;
        private boolean isParagraphStart = false;
        private boolean isPageBreak = false;
        private boolean isHangingIndent = false;
        private boolean isArticleStart = false;
        private TextPosition position = null;

        PositionWrapper(TextPosition position) {
            this.position = position;
        }

        public TextPosition getTextPosition() {
            return this.position;
        }

        public boolean isLineStart() {
            return this.isLineStart;
        }

        public void setLineStart() {
            this.isLineStart = true;
        }

        public boolean isParagraphStart() {
            return this.isParagraphStart;
        }

        public void setParagraphStart() {
            this.isParagraphStart = true;
        }

        public boolean isArticleStart() {
            return this.isArticleStart;
        }

        public void setArticleStart() {
            this.isArticleStart = true;
        }

        public boolean isPageBreak() {
            return this.isPageBreak;
        }

        public void setPageBreak() {
            this.isPageBreak = true;
        }

        public boolean isHangingIndent() {
            return this.isHangingIndent;
        }

        public void setHangingIndent() {
            this.isHangingIndent = true;
        }
    }
    LinkedList<ResVO> linkedList = new LinkedList<ResVO>();

    @Override
    protected void writePage() throws IOException {
        float maxYForLine = -3.4028235E38F;
        float minYTopForLine = 3.4028235E38F;
        float endOfLastTextX = -1.0F;
        float lastWordSpacing = -1.0F;
        float maxHeightForLine = -1.0F;
        CustomTextStripper.PositionWrapper lastPosition = null;
        CustomTextStripper.PositionWrapper lastLineStartPosition = null;
        boolean startOfPage = true;
        if (this.charactersByArticle.size() > 0) {
            this.writePageStart();
        }

        for (Iterator i$ = this.charactersByArticle.iterator(); i$.hasNext(); this.endArticle()) {
            List<TextPosition> textList = (List) i$.next();
            if (this.getSortByPosition()) {
                TextPositionComparator comparator = new TextPositionComparator();
                if (useCustomQuickSort) {
                    QuickSort.sort(textList, comparator);
                } else {
                    Collections.sort(textList, comparator);
                }
            }

            this.startArticle();
            boolean startOfArticle = true;
            List<CustomTextStripper.LineItem> line = new ArrayList();
            Iterator<TextPosition> textIter = textList.iterator();

            float averageCharWidth = 0.0f;
            for (float previousAveCharWidth = -1.0F; textIter.hasNext(); previousAveCharWidth = averageCharWidth) {
                TextPosition position = (TextPosition) textIter.next();
                if (position.getFontSize() < 10) continue;
                CustomTextStripper.PositionWrapper current = new CustomTextStripper.PositionWrapper(position);
                String characterValue = position.getUnicode();
                if (lastPosition != null && (position.getFont() != lastPosition.getTextPosition().getFont() || position.getFontSize() != lastPosition.getTextPosition().getFontSize())) {
                    previousAveCharWidth = -1.0F;
                }

                float positionX;
                float positionY;
                float positionWidth;
                float positionHeight;
                if (this.getSortByPosition()) {
                    positionX = position.getXDirAdj();
                    positionY = position.getYDirAdj();
                    positionWidth = position.getWidthDirAdj();
                    positionHeight = position.getHeightDir();
                } else {
                    positionX = position.getX();
                    positionY = position.getY();
                    positionWidth = position.getWidth();
                    positionHeight = position.getHeight();
                }

                int wordCharCount = position.getIndividualWidths().length;
                float wordSpacing = position.getWidthOfSpace();
                float deltaSpace;
                if (wordSpacing != 0.0F && !Float.isNaN(wordSpacing)) {
                    if (lastWordSpacing < 0.0F) {
                        deltaSpace = wordSpacing * this.getSpacingTolerance();
                    } else {
                        deltaSpace = (wordSpacing + lastWordSpacing) / 2.0F * this.getSpacingTolerance();
                    }
                } else {
                    deltaSpace = 3.4028235E38F;
                }

                if (previousAveCharWidth < 0.0F) {
                    averageCharWidth = positionWidth / (float) wordCharCount;
                } else {
                    averageCharWidth = (previousAveCharWidth + positionWidth / (float) wordCharCount) / 2.0F;
                }

                float deltaCharWidth = averageCharWidth * this.getAverageCharTolerance();
                float expectedStartOfNextWordX = -3.4028235E38F;
                if (endOfLastTextX != -1.0F) {
                    if (deltaCharWidth > deltaSpace) {
                        expectedStartOfNextWordX = endOfLastTextX + deltaSpace;
                    } else {
                        expectedStartOfNextWordX = endOfLastTextX + deltaCharWidth;
                    }
                }

                if (lastPosition != null) {
                    if (startOfArticle) {
                        lastPosition.setArticleStart();
                        startOfArticle = false;
                    }

                    if (!this.overlap(positionY, positionHeight, maxYForLine, maxHeightForLine)) {
                        lastLineStartPosition = this.handleLineSeparation(current, lastPosition, lastLineStartPosition, maxHeightForLine,line);
                        this.writeLine(this.normalize(line));
                        line.clear();
                        expectedStartOfNextWordX = -3.4028235E38F;
                        maxYForLine = -3.4028235E38F;
                        maxHeightForLine = -1.0F;
                        minYTopForLine = 3.4028235E38F;
                    }

                    if (expectedStartOfNextWordX != -3.4028235E38F && expectedStartOfNextWordX < positionX && lastPosition.getTextPosition().getUnicode() != null && !lastPosition.getTextPosition().getUnicode().endsWith(" ")) {
                        line.add(CustomTextStripper.LineItem.getWordSeparator());
                    }
                }

                if (positionY >= maxYForLine) {
                    maxYForLine = positionY;
                }

                endOfLastTextX = positionX + positionWidth;
                if (characterValue != null) {
                    if (startOfPage && lastPosition == null) {
                        this.writeParagraphStart();
                    }

                    line.add(new CustomTextStripper.LineItem(position));
                }

                maxHeightForLine = Math.max(maxHeightForLine, positionHeight);
                minYTopForLine = Math.min(minYTopForLine, positionY - positionHeight);
                lastPosition = current;
                if (startOfPage) {
//                    current.setParagraphStart();
                    current.setLineStart();
                    lastLineStartPosition = current;
                    startOfPage = false;
                }

                lastWordSpacing = wordSpacing;
            }

            if (line.size() > 0) {
                this.writeLine(this.normalize(line));
                this.writeParagraphEnd();
            }
        }

        this.writePageEnd();
    }

    private CustomTextStripper.PositionWrapper handleLineSeparation(CustomTextStripper.PositionWrapper current, CustomTextStripper.PositionWrapper lastPosition, CustomTextStripper.PositionWrapper lastLineStartPosition, float maxHeightForLine,List<CustomTextStripper.LineItem> line) throws IOException {
       ResVO temp =  new ResVO(current,lastPosition,lastLineStartPosition,maxHeightForLine,line);
       current.setLineStart();
        if (linkedList.size()==0){
            linkedList.offer(temp);
        }else {
            ResVO last = linkedList.poll();
            linkedList.offer(temp);
            this.isParagraphSeparation(last.current, last.lastPosition, last.lastLineStartPosition, last.maxHeightForLine,last.line);
            if (last.current.isParagraphStart()) {
                if (lastPosition.isArticleStart()) {
                    if (lastPosition.isLineStart()) {
                        this.writeLineSeparator();
                    }

                    this.writeParagraphStart();
                } else {
                    this.writeLineSeparator();
                    this.writeParagraphSeparator();
                }
            } else {
                this.writeLineSeparator();
            }
        }
        return current;
    }

    private void writeLine(List<CustomTextStripper.WordWithTextPositions> line) throws IOException {
        int numberOfStrings = line.size();

        for (int i = 0; i < numberOfStrings; ++i) {
            CustomTextStripper.WordWithTextPositions word = (CustomTextStripper.WordWithTextPositions) line.get(i);
            this.writeString(word.getText(), word.getTextPositions());
            if (i < numberOfStrings - 1) {
                this.writeWordSeparator();
            }
        }

    }

    private boolean overlap(float y1, float height1, float y2, float height2) {
        return this.within(y1, y2, 0.1F) || y2 <= y1 && y2 >= y1 - height1 || y1 <= y2 && y1 >= y2 - height2;
    }

    private CustomTextStripper.WordWithTextPositions createWord(String word, List<TextPosition> wordPositions) {
        return new CustomTextStripper.WordWithTextPositions(this.normalizeWord(word), wordPositions);
    }

    private StringBuilder normalizeAdd(List<CustomTextStripper.WordWithTextPositions> normalized, StringBuilder lineBuilder, List<TextPosition> wordPositions, CustomTextStripper.LineItem item) {
        if (item.isWordSeparator()) {
            normalized.add(this.createWord(lineBuilder.toString(), new ArrayList(wordPositions)));
            lineBuilder = new StringBuilder();
            wordPositions.clear();
        } else {
            TextPosition text = item.getTextPosition();
            lineBuilder.append(text.getUnicode());
            wordPositions.add(text);
        }

        return lineBuilder;
    }

    private List<CustomTextStripper.WordWithTextPositions> normalize(List<CustomTextStripper.LineItem> line) {
        List<CustomTextStripper.WordWithTextPositions> normalized = new LinkedList();
        StringBuilder lineBuilder = new StringBuilder();
        List<TextPosition> wordPositions = new ArrayList();

        CustomTextStripper.LineItem item;
        for (Iterator i$ = line.iterator(); i$.hasNext(); lineBuilder = this.normalizeAdd(normalized, lineBuilder, wordPositions, item)) {
            item = (CustomTextStripper.LineItem) i$.next();
        }

        if (lineBuilder.length() > 0) {
            normalized.add(this.createWord(lineBuilder.toString(), wordPositions));
        }

        return normalized;
    }

    private boolean within(float first, float second, float variance) {
        return second < first + variance && second > first - variance;
    }

    private static final class WordWithTextPositions {
        String text;
        List<TextPosition> textPositions;

        WordWithTextPositions(String word, List<TextPosition> positions) {
            this.text = word;
            this.textPositions = positions;
        }

        public String getText() {
            return this.text;
        }

        public List<TextPosition> getTextPositions() {
            return this.textPositions;
        }
    }

    private String handleDirection(String word) {
        Bidi bidi = new Bidi(word, -2);
        if (!bidi.isMixed() && bidi.getBaseLevel() == 0) {
            return word;
        } else {
            int runCount = bidi.getRunCount();
            byte[] levels = new byte[runCount];
            Integer[] runs = new Integer[runCount];

            for (int i = 0; i < runCount; ++i) {
                levels[i] = (byte) bidi.getRunLevel(i);
                runs[i] = i;
            }

            Bidi.reorderVisually(levels, 0, runs, 0, runCount);
            StringBuilder result = new StringBuilder();

            for (int i = 0; i < runCount; ++i) {
                int index = runs[i];
                int start = bidi.getRunStart(index);
                int end = bidi.getRunLimit(index);
                int level = levels[index];
                if ((level & 1) != 0) {
                    while (true) {
                        --end;
                        if (end < start) {
                            break;
                        }

                        char character = word.charAt(end);
                        if (Character.isMirrored(word.codePointAt(end))) {
                            if (MIRRORING_CHAR_MAP.containsKey(character)) {
                                result.append(MIRRORING_CHAR_MAP.get(character));
                            } else {
                                result.append(character);
                            }
                        } else {
                            result.append(character);
                        }
                    }
                } else {
                    result.append(word, start, end);
                }
            }

            return result.toString();
        }
    }

    private static Map<Character, Character> MIRRORING_CHAR_MAP;

    private float multiplyFloat(float value1, float value2) {
        return (float) Math.round(value1 * value2 * 1000.0F) / 1000.0F;
    }
    public static boolean ifList(List<CustomTextStripper.LineItem> line) {
        if (line == null) {
            return false;
        }
        StringBuilder sb = new StringBuilder("");
        boolean res = false;
        for (int i = 0; i < line.size(); i++) {

                LineItem lineItem = line.get(i);
                if (lineItem.getTextPosition() == null) {
                    sb.append(" ");
                    continue;
                }
                String unicode = lineItem.getTextPosition().getUnicode();
                sb.append(unicode);
        }
        String pre = sb.toString();
        String first = pre.substring(0, 1);
        String total = "\\d(\\.(\\s)*(\\d)*)*[\\s|[\\s\\p{Zs}]]+.*";
//        String total = "\\d(\\.(\\s)*(\\d)*)*[\\s\\p{Zs}]*([\\u4E00-\\u9FA5]|\\d|(\\s)*|\\w)*";
//        String total = "\\d(\\.\\d)*[\\s\\p{Zs}]+([\\u4E00-\\u9FA5]|\\d|\\w)*";
        Pattern r = Pattern.compile(total);
        Matcher m = r.matcher(pre);
        if (first.matches("[0-9]")) {
            if (m.matches()) {
                res = true;
                return res;
            }
        }else if (first.equals("(")){
            if (pre.substring(1,2).matches("\\d")){
                res = true;
                return res;
            }

        }
        return res;
    }

    private void isParagraphSeparation(CustomTextStripper.PositionWrapper position, CustomTextStripper.PositionWrapper lastPosition, CustomTextStripper.PositionWrapper lastLineStartPosition, float maxHeightForLine,List<CustomTextStripper.LineItem> line) {
        boolean result = false;
        boolean iflist = ifList(line);
            if (iflist){
                result = true;
            }else {
            if (lastLineStartPosition == null) {
                    result = true;
                }
            else {
                // 当前行与上一行的纵间距+当前行的字高
                float yGap = Math.abs(position.getTextPosition().getYDirAdj() - lastPosition.getTextPosition().getYDirAdj());
                // 当前行开头与上一行开头的横间距
                float xGap = position.getTextPosition().getXDirAdj() - lastLineStartPosition.getTextPosition().getXDirAdj();
                // 下降阈值默认为2.5，缩进阈值默认为2.0,maxHeightline为当前行字高，getWidthOfSpace为当前行每个字体的宽度。
                // newYVal为2.5×当前行字高并取整；newXVal为2.0×当前单个字宽，并取整。positionWidth为0.25×单个字符字宽并取整
                float newYVal = this.multiplyFloat(this.getDropThreshold(), maxHeightForLine);
                float newXVal = this.multiplyFloat(this.getIndentThreshold(), position.getTextPosition().getWidthOfSpace());
                float positionWidth = this.multiplyFloat(0.25F, position.getTextPosition().getWidth());
                float posFontSize = position.getTextPosition().getFontSize();
                float lastPosFontSize = lastLineStartPosition.getTextPosition().getFontSize();
                float defYgap = position.getTextPosition().getYDirAdj() - lastPosition.getTextPosition().getYDirAdj();
                float defXgap = position.getTextPosition().getXDirAdj() - lastPosition.getTextPosition().getXDirAdj();
                float posWidth = position.getTextPosition().getWidth();
                String curPos = position.getTextPosition().getUnicode();
                String lastUnicode = lastLineStartPosition.getTextPosition().getUnicode();
                // 当前行的底部与上一行的底部的距离是否大于2.5倍的当前行高
                if (yGap > newYVal) {
                    int threePosWidth = (int) position.getTextPosition().getWidth() * 3;
                    boolean leftJoinRight = Math.abs(defYgap) > 150  && posFontSize==lastPosFontSize;
                    boolean specialCase = Math.abs(defYgap)> 150 && posFontSize ==lastPosFontSize && Math.abs(defXgap) <= threePosWidth;
                    Float twoPosWidth = 2 * posWidth;
                    if (curPos.matches("[a-zA-Z0-9]")) {
                        twoPosWidth = twoPosWidth * 2;
                    }
                    int round = Math.round(twoPosWidth);
                    if (specialCase) {
                        result = true;
                    } else if (leftJoinRight)
                        result = false;
                    else if (curPos.equals("("))
                        result = false;
                    else if (posFontSize == lastPosFontSize &&curPos.equals("引"))
                        result = true;
                    else if (posFontSize == lastPosFontSize) {
                        if (curPos.matches("[a-zA-Z0-9]")) {
                            xGap = Math.round(xGap - posWidth/ 2);
                        }
                        if (curPos.equals("　") && lastUnicode.equals("　"))
                            result = true;
                        else if (xGap == round) result = true;
                        else if (lastUnicode.matches("\\d")) result=true;
                        else result = false;
                    } else result = true;
                    // 如果纵向间距满足要求，判断当前行与上一行开头的横坐标间距是否大于两个字符宽度
                } else if (xGap > newXVal) {
                    float ab = position.getTextPosition().getFontSize();
                    float ab1 = 7.72318f;
                    if (!lastLineStartPosition.isParagraphStart()) {
                        if (position.getTextPosition().getYDirAdj() - lastPosition.getTextPosition().getYDirAdj() < 0) {
                            result = false;
                        } else if (ab == ab1) result = false;
                        else result = true;
                    } else {
                        position.setHangingIndent();
                    }
                } else if (xGap < -position.getTextPosition().getWidthOfSpace()) {
                    if (!lastLineStartPosition.isParagraphStart()) {
                        if (lastLineStartPosition.position.getUnicode().equals("[")) {
                            result = false;
                        } else if (position.getTextPosition().getFontSize() == lastLineStartPosition.getTextPosition().getFontSize()) {
                            result = false;
                        } else
                            result = true;
                    }
                }
                else if (Math.abs(xGap) < positionWidth){
//                    Pattern liPattern = this.matchListItemPattern(lastLineStartPosition);
//                    if (liPattern != null) {
//                        Pattern currentPattern = this.matchListItemPattern(position);
//                        if (liPattern == currentPattern) {
//                            result = true;
//                        }
//                    }
//                    else if (Math.abs(xGap) < positionWidth) {
                    if (lastLineStartPosition.isHangingIndent()) {
                        position.setHangingIndent();
                    }
                    else if (lastLineStartPosition.isParagraphStart()) {
                        if (xGap == 0) {
                            String unicode = lastLineStartPosition.getTextPosition().getUnicode();
                            String kg = "　";
                            boolean dd = unicode.equals(kg);
                            boolean ee = !position.getTextPosition().getUnicode().equals(" ");
                            if (dd && ee)
                                result = false;
                            else result = true;
                        } else if (lastLineStartPosition
                                .getTextPosition().getUnicode().equals("(") && lastLineStartPosition.isParagraphStart())
                            result = true;
                    }
                }
            }

//                    }
//                    else if (position.getTextPosition().getUnicode().equals("(") && lastPosition.getTextPosition().getUnicode().equals("。")) {
//                        result = true;
//                    }
//            else if (position.getTextPosition().getUnicode().matches("[0-9]+") && lastPosition.getTextPosition().getUnicode().equals("。")) {
//                        result = true;
//                    }
//            else if (lastLineStartPosition.getTextPosition().getUnicode().matches("[0-9]+") && xGap >= 2 * lastLineStartPosition.getTextPosition().getWidth())
//                        result = true;
                }

                if (result) {
                    position.setParagraphStart();
                }

            }
    private Pattern matchListItemPattern(CustomTextStripper.PositionWrapper pw) {
        TextPosition tp = pw.getTextPosition();
        String txt = tp.getUnicode();
        return matchPattern(txt, this.getListItemPatterns());
    }
        private static float defaultIndentThreshold = 2.0F;
        private static float defaultDropThreshold = 2.5F;
        private static final Log LOG = LogFactory.getLog(PDFTextStripper.class);
        private String normalizeWord (String word){
            StringBuilder builder = null;
            int p = 0;
            int q = 0;

            for (int strLength = word.length(); q < strLength; ++q) {
                char c = word.charAt(q);
                if ('ﬀ' <= c && c <= '\ufdff' || 'ﹰ' <= c && c <= '\ufeff') {
                    if (builder == null) {
                        builder = new StringBuilder(strLength * 2);
                    }

                    builder.append(word.substring(p, q));
                    if (c != 'ﷲ' || q <= 0 || word.charAt(q - 1) != 1575 && word.charAt(q - 1) != 'ﺍ') {
                        builder.append(Normalizer.normalize(word.substring(q, q + 1), Normalizer.Form.NFKC).trim());
                    } else {
                        builder.append("لله");
                    }

                    p = q + 1;
                }
            }

            if (builder == null) {
                return this.handleDirection(word);
            } else {
                builder.append(word.substring(p, q));
                return this.handleDirection(builder.toString());
            }
        }
        static {
            String path = null;
            String version = null;

            try {
                String className = PDFTextStripper.class.getSimpleName().toLowerCase();
                String prop = className + ".indent";
                version = System.getProperty(prop);
                prop = className + ".drop";
                path = System.getProperty(prop);
            } catch (SecurityException var22) {
            }

            if (version != null && version.length() > 0) {
                try {
                    defaultIndentThreshold = Float.parseFloat(version);
                } catch (NumberFormatException var21) {
                }
            }

            if (path != null && path.length() > 0) {
                try {
                    defaultDropThreshold = Float.parseFloat(path);
                } catch (NumberFormatException var20) {
                }
            }

            boolean is16orLess = false;

            try {
                version = System.getProperty("java.specification.version");
                StringTokenizer st = new StringTokenizer(version, ".");
                int majorVersion = Integer.parseInt(st.nextToken());
                int minorVersion = 0;
                if (st.hasMoreTokens()) {
                    minorVersion = Integer.parseInt(st.nextToken());
                }

                is16orLess = majorVersion == 1 && minorVersion <= 6;
            } catch (SecurityException var23) {
            } catch (NumberFormatException var24) {
            }

            useCustomQuickSort = !is16orLess;
//            LIST_ITEM_EXPRESSIONS = new String[]{"\\.", "\\d+\\.", "\\[\\d+\\]", "\\d+\\)", "[A-Z]\\.", "[a-z]\\.", "[A-Z]\\)", "[a-z]\\)", "[IVXL]+\\.", "[ivxl]+\\."};
            MIRRORING_CHAR_MAP = new HashMap();
            path = "org/apache/pdfbox/resources/text/BidiMirroring.txt";
            InputStream input = PDFTextStripper.class.getClassLoader().getResourceAsStream(path);

            try {
                parseBidiFile(input);
            } catch (IOException var18) {
                LOG.warn("Could not parse BidiMirroring.txt, mirroring char map will be empty: " + var18.getMessage());
            } finally {
                try {
                    input.close();
                } catch (IOException var17) {
                    LOG.error("Could not close BidiMirroring.txt ", var17);
                }

            }

        }
        private static void parseBidiFile (InputStream inputStream) throws IOException {
            LineNumberReader rd = new LineNumberReader(new InputStreamReader(inputStream));

            while (true) {
                String s;
                do {
                    s = rd.readLine();
                    if (s == null) {
                        return;
                    }

                    int comment = s.indexOf(35);
                    if (comment != -1) {
                        s = s.substring(0, comment);
                    }
                } while (s.length() < 2);

                StringTokenizer st = new StringTokenizer(s, ";");
                int nFields = st.countTokens();
                Character[] fields = new Character[nFields];

                for (int i = 0; i < nFields; ++i) {
                    fields[i] = (char) Integer.parseInt(st.nextToken().trim(), 16);
                }

                if (fields.length == 2) {
                    MIRRORING_CHAR_MAP.put(fields[0], fields[1]);
                }
            }
        }


    }

